package com.societyGames.codeAlong.state.codeExercise.model
{
import com.societyGames.codeAlong.state.codeExercise.model.help.ExceptionHelpFactory;
import com.societyGames.codeAlong.state.codeExercise.model.help.IExceptionHelp;
import com.societyGames.codeAlong.state.codeExercise.model.help.ISyntaxErrorHelp;
import com.societyGames.codeAlong.state.codeExercise.model.help.SyntaxErrorHelpFactory;
import com.societyGames.utility.XMLDictionary;

public class ModuleData
{
  public var id:uint;
  public var name:String;
  public var canComplete:Boolean;
  public var cases:Vector.<CaseData> = new Vector.<CaseData>();
  public var terms:Vector.<TermData> = new Vector.<TermData>();
  public var goal:String;
  public var hint:String;
  public var libraryData:LibraryData;
  public var index:int;
  public var codeBegin:String; //Extra code inserted by module at beginning. May be null.
  public var codeEnd:String;   //Extra code inserted by module at end. May be null.
  public var syntaxErrorHelps:Vector.<ISyntaxErrorHelp> = new Vector.<ISyntaxErrorHelp>();
  public var exceptionHelps:Vector.<IExceptionHelp> = new Vector.<IExceptionHelp>();
  public var termIndex:int; //For example, 4 would mean first 4 terms should be shown.
  public var functionIndex:int;
  public var actionsXML:XML;

  public static function fromXml(xml:XML, xmlDictionary:XMLDictionary, index:int):ModuleData
  {
    var moduleData:ModuleData = new ModuleData();
    moduleData.id = xml.@id;
    moduleData.name = xml.@name;
    if (xml.hasOwnProperty("@canComplete"))
    {
      moduleData.canComplete = xml.@canComplete == "true";
    }
    else
    {
      moduleData.canComplete = true;
    }
    for each (var caseXml:XML in xml["case"]) //Use ["case"] because case is keyword and won't work E4X
    {
      var caseData:CaseData = CaseData.fromXml(caseXml);
      moduleData.cases.push(caseData);
    }
    if (moduleData.cases.length == 0) //TODO: We might not need this if we have cases that insta complete?
    {
      throw new ArgumentError("Module must have at least one case.");
    }
    for each (var termXml:XML in xml.term)
    {
      var termData:TermData = TermData.fromXml(termXml);
      moduleData.terms.push(termData);
    }
    moduleData.goal = xml.goal[0].toString();
    moduleData.hint = xml.hint[0].toString();
    moduleData.libraryData = LibraryData.fromXml(xml.library[0]);
    moduleData.index = index;
    if ("codeBegin" in xml)
    {
      moduleData.codeBegin = xmlDictionary.lookUp(xml.codeBegin[0]).toString();
    }
    if ("codeEnd" in xml)
    {
      moduleData.codeEnd = xmlDictionary.lookUp(xml.codeEnd[0]).toString();
    }
    if ("syntaxErrors" in xml)
    {
      for each (var syntaxErrorXml:XML in xml.syntaxErrors.syntaxError)
      {
        var syntaxErrorHelp:ISyntaxErrorHelp = SyntaxErrorHelpFactory.create(syntaxErrorXml);
        moduleData.syntaxErrorHelps.push(syntaxErrorHelp);
      }
    }
    if ("exceptions" in xml)
    {
      for each (var exceptionXml:XML in xml.exceptions.exception)
      {
        var exceptionHelp:IExceptionHelp = ExceptionHelpFactory.create(exceptionXml);
        moduleData.exceptionHelps.push(exceptionHelp);
      }
    }
    if ("actions" in xml)
    {
      moduleData.actionsXML = xml.actions[0];
    }
    return moduleData;
  }
}
}